﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Draco.OWF.DataBinding;
using Draco.OWF.RT;
using System.Threading;

namespace Draco.OWF.RT.Engine
{
    public class AbstractEngine:IEngine
    {
        protected List<IProcess> m_ProcessCollection=new List<IProcess>();
        protected List<IWorkerEngine> m_WorkerEngines = new List<IWorkerEngine>();

        public virtual void Initialize()
        {
            
        }
        public virtual void LoadProcess(IProcess process)
        {
            if (process != null && !IsProcessLoaded(process.Id))
                m_ProcessCollection.Add(process);
        }
        public virtual IProcess LoadProcess(String fileName)
        {
            return null;
        }

        /// <summary>
        /// Get Loaded processes
        /// </summary>
        public IList<IProcess> LoadedProcesses
        {
            get { return m_ProcessCollection; }
        }

        /// <summary>
        /// Get All Jobs
        /// </summary>
        public IList<IJob> AllJobs
        {
            get 
            {
                IList<IJob> jobs = new List<IJob>();
                foreach(IWorkerEngine worker in m_WorkerEngines)
                {
                    jobs.Add(worker.Job);
                }
                return jobs;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public IList<IJob> AllRunningJobs
        {
            get
            {
                IList<IJob> jobs = new List<IJob>();
                foreach (IWorkerEngine worker in m_WorkerEngines)
                {
                    if (worker.Job.Status== WFProcessStatus.Running)
                        jobs.Add(worker.Job);
                }
                return jobs;
            }
        }

        public virtual IJob CreateJob(IProcess process, IBindingDataItemCollection Arguments, IJobContext parentContext)
        {
            if (process == null)
                throw new ArgumentNullException("process is null");
            IWorkerEngine worker = CreateWorkerEngine(process, Arguments);
            m_WorkerEngines.Add(worker);
            ThreadPool.QueueUserWorkItem(new WaitCallback(worker.Start));
            return worker.Job;
        }

        protected virtual bool IsProcessLoaded(String WorkflowProcessId)
        {
            foreach (var process in m_ProcessCollection)
            {
                if (process.Id == WorkflowProcessId)
                    return true;
            }
            return false;
        }

        public virtual void Dispose()
        {

        }

        /// <summary>
        /// Create a new WorkerEngine,user can override this methed in subclass
        /// </summary>
        /// <param name="process"></param>
        /// <returns></returns>
        protected virtual IWorkerEngine CreateWorkerEngine(IProcess process, IBindingDataItemCollection Arguments)
        {
            return new WorkerEngine(process, Arguments);
        }
    }
}
